#!/bin/sh
# Copyright (c) 2012, bkil.hu
# This program is free software and can be distributed under the terms of
# the GNU General Public License v2,
# see COPYING for detailed licensing terms.
# created on 2012-06-09
#
#Operation:
# This program continuously downloads a file at a very low rate.
# It pauses the download if it perceives that the current network usage has
# been low for some time (conceptually idle).
#
#Concept:
# It is mostly useful for 3G cellular data networks to keep the network from
# entering a power saving state to reduce page loading latency.
# I don't have technical details (please post on the mailing list if you do),
# but my basic founding is the following.
# A modem can be registered and connected on the network, ready to accept
# packets, but from which wakup could take either 400-600ms or
# multiple seconds.
# This state is entered automatically either after a few seconds of inactivity
# or if the transfer rate goes below a certain level.
#
# From user level, clicking a link in your web browser could very well do
# nothing for seconds before the page even starts to load, lowering user
# satisfaction.
# This effect could be easily verified by loading a given page in a fast browser
# (like links2) and force reloading it.
# When the link is in power saving, the reload takes at least half a second,
# otherwise it is less than 100ms.

main() {
 local MINTR=10000 # Byte/s, min transfer speed considered non-idle
 local MAXIDLE=999 # seconds, max idle time before pausing download
 local IFACE=ppp0 # which network interface to monitor
 download_loop &
 local PID=$!
 local SIGS="2 3 9 15"
 trap "term $PID; exit" $SIGS
 while true ; do
  local TIME=0
  local SUM=0
  local PREVSUM=0
  while
   [ $TIME -lt $MAXIDLE ]
  do
   sleep 1
   PREVSUM=$SUM
   SUM=`sum_transferred $IFACE`
   if [ `expr $SUM - $PREVSUM` -lt $MINTR ] ; then
    local TIME=`expr $TIME + 1`
   else
    local TIME=0
   fi
  done
  sigall -STOP $PID
  date "+%Y%m%dT%H%M%S stop" >&2
  while
   [ `expr $SUM - $PREVSUM` -lt $MINTR ]
  do
   sleep 1
   PREVSUM=$SUM
   SUM=`sum_transferred $IFACE`
  done
  date "+%Y%m%dT%H%M%S cont" >&2
  sigall -CONT $PID
 done
 term $PID
 trap - $SIGS
}

sum_transferred() {
 SUM=`sum_transferred_ "$@"`
 date "+%Y%m%dT%H%M%S $SUM" >&2
 echo $SUM
}

sum_transferred_() {
 ifconfig $1 |
 grep bytes |
 sed -r "s~^.*bytes:([0-9]+) .*bytes:([0-9]+) .*$~\1 \2~" |
 awk '
  {
   s += $1 + $2
  }
  END {
   print s
  }'
}

term() {
 sigall -CONT $1
 sleep 1
 sigall -TERM $1
 sleep 1
 sigall -9 $1
}

sigall() {
 kill $1 `subtree $2`
}

subtree() {
 echo $1
 for CHILD in `pgrep -P $1` ; do
  subtree $CHILD
 done
}

download_loop() {
 while true
 do
  download_single
 done
}

download_single() {
 # any file would do from the ISP, ideally should be >1MB
 URL="http://www.t-mobile.hu/static/DocumentStore/lakossagi/ugyintezes/aszf/e_m2_120401.pdf"

 # MTU/2 resulted in 1 1500B packet/2 sec RX, 1 40B packet/sec TX
 BLOCK=750
 wget --limit-rate $BLOCK -O - $URL > /dev/null 2>/dev/null
}

main "$@"
